/*
 * Copyright 2017 yetao &lt;yetao_ustc@163.com&gt;.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package date.yetao.maven.all.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 专门用于处理代码名字的相关工具，如：类名、变量名、包名等
 * <P>
 *
 * @author yetao &lt;yetao_ustc@163.com&gt;
 */
public class CodeNameTools {

    /**
     * 小数点分割
     */
    public static final String SPLIT_DOT = ".";
    /**
     * 中线分割
     */
    public static final String SPLIT_MIDDLE_LINE = "-";
    /**
     * 下划线分割
     */
    public static final String SPLIT_UNDER_LINE = "_";

    // 所有的种类
    public static final String CASE_AllUpperCase = "AllUpperCase";
    public static final String CASE_AllLowerCase = "AllLowerCase";
    public static final String CASE_FirstUpperCamelCase = "FirstUpperCamelCase";
    public static final String CASE_FirstLowerCamelCase = "FirstLowerCamelCase";
    public static final String CASE_UnderLineSplitCase = "UnderLineSplitCase";
    public static final String CASE_MiddleLineSplitCase = "MiddleLineSplitCase";
    public static final String CASE_DotSplitCase = "DotSplitCase";
    public static final Map<String, Integer> PRIORITY_MAP = new HashMap<>();

    static {
        PRIORITY_MAP.put(CASE_AllLowerCase, 1);
        PRIORITY_MAP.put(CASE_AllUpperCase, 2);
        PRIORITY_MAP.put(CASE_FirstLowerCamelCase, 3);
        PRIORITY_MAP.put(CASE_FirstUpperCamelCase, 4);
        PRIORITY_MAP.put(CASE_UnderLineSplitCase, 5);
        PRIORITY_MAP.put(CASE_DotSplitCase, 6);
        PRIORITY_MAP.put(CASE_MiddleLineSplitCase, 7);
    }

    /**
     * 智能替换给定text中的名称字符串，根据所有的名称类型进行全匹配
     * <P>
     * 如：code-nameTools，可以根据模板智能替换为：CodeNameTools.toMiddleLineSplitCase(conf.moduleName)
     * <P>
     * 使用的模板为：CodeNameTools.to$$1$$(conf.moduleName)
     * <P>
     *
     * @param codeName 需要替换的变量名称
     * @param replaceTemplate 替换后的模板，用$$1$$指定类别占位
     * @param oriText 原始的字符串
     * @return
     */
    public static String smartNameReplace(String codeName, String replaceTemplate, String oriText) {
        Map<String, String> caseMap = toAllCase(codeName);
        List<Map.Entry<String, String>> entryList = new ArrayList<>(caseMap.entrySet());
        // 按照权重对key进行排序
        Collections.sort(entryList, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                int dif = -(o1.getValue().length() - o2.getValue().length());
                if (dif != 0) {
                    return dif;
                }
                return -(PRIORITY_MAP.get(o1.getKey()) - PRIORITY_MAP.get(o2.getKey()));
            }
        });

        Map<String, String> replaceMap = new LinkedHashMap<>();
        for (Map.Entry<String, String> entry : entryList) {
            replaceMap.put(entry.getValue(), replaceTemplate.replace("$$1$$", entry.getKey()));
        }

        return StringTools.replaceAll(oriText, replaceMap, false, false);
    }

    /**
     * 智能分割名称
     * <P>
     *
     * @param name
     * @return
     */
    public static String[] autoSplit(String name) {
        if (name.contains(SPLIT_DOT)) {
            return name.toLowerCase().split("\\.");
        } else if (name.contains(SPLIT_MIDDLE_LINE)) {
            return name.toLowerCase().split(SPLIT_MIDDLE_LINE);
        } else if (name.contains(SPLIT_UNDER_LINE)) {
            return name.toLowerCase().split(SPLIT_UNDER_LINE);
        } else {
            List<String> list = new ArrayList<>();
            StringBuilder sb = new StringBuilder();
            for (char ch : name.toCharArray()) {
                if (Character.isUpperCase(ch)) {
                    // 大写字母，需要处理
                    if (sb.length() > 0) {
                        list.add(sb.toString().toLowerCase());
                        sb = new StringBuilder();
                    }
                }
                sb.append(ch);
            }
            list.add(sb.toString().toLowerCase());
            String[] arrs = new String[list.size()];
            arrs = list.toArray(arrs);
            return arrs;
        }
    }

    /**
     * 将原始的名称经过解析后转化为所有支持的模式
     * <P>
     *
     * @param name
     * @return
     */
    public static Map<String, String> toAllCase(String name) {
        String[] parts = autoSplit(name);
        Map<String, String> map = new HashMap<>();
        map.put(CASE_AllLowerCase, toAllLowerCase(parts));
        map.put(CASE_AllUpperCase, toAllUpperCase(parts));
        map.put(CASE_FirstLowerCamelCase, toFirstLowerCamelCase(parts));
        map.put(CASE_FirstUpperCamelCase, toFirstUpperCamelCase(parts));
        map.put(CASE_UnderLineSplitCase, toUnderLineSplitCase(parts));
        map.put(CASE_DotSplitCase, toDotSplitCase(parts));
        map.put(CASE_MiddleLineSplitCase, toMiddleLineSplitCase(parts));
        return map;
    }

    /**
     * 将原始的名称经过解析后转化为全大写模式
     * <P>
     *
     * @param parts
     * @return
     */
    public static String toAllUpperCase(String[] parts) {
        StringBuilder sb = new StringBuilder();
        for (String part : parts) {
            sb.append(StringTools.toUpperCase(part));
        }
        return sb.toString();
    }

    /**
     * 将原始的名称经过解析后转化为全大写模式
     * <P>
     *
     * @param name
     * @return
     */
    public static String toAllUpperCase(String name) {
        String[] parts = autoSplit(name);
        return toAllUpperCase(parts);
    }

    /**
     * 将原始的名称经过解析后转化为全小写模式
     * <P>
     *
     * @param parts
     * @return
     */
    public static String toAllLowerCase(String[] parts) {
        StringBuilder sb = new StringBuilder();
        for (String part : parts) {
            sb.append(StringTools.toLowerCase(part));
        }
        return sb.toString();
    }

    /**
     * 将原始的名称经过解析后转化为全小写模式
     * <P>
     *
     * @param name
     * @return
     */
    public static String toAllLowerCase(String name) {
        String[] parts = autoSplit(name);
        return toAllLowerCase(parts);
    }

    /**
     * 将原始的名称经过解析后转化为首字母大写驼峰模式
     * <P>
     *
     * @param parts
     * @return
     */
    public static String toFirstUpperCamelCase(String[] parts) {
        StringBuilder sb = new StringBuilder();
        for (String part : parts) {
            sb.append(StringTools.toUpperCaseFirstOne(part));
        }
        return sb.toString();
    }

    /**
     * 将原始的名称经过解析后转化为首字母大写驼峰模式
     * <P>
     *
     * @param name
     * @return
     */
    public static String toFirstUpperCamelCase(String name) {
        String[] parts = autoSplit(name);
        return toFirstUpperCamelCase(parts);
    }

    /**
     * 将原始的名称经过解析后转化为首字母小写驼峰模式
     * <P>
     *
     * @param parts
     * @return
     */
    public static String toFirstLowerCamelCase(String[] parts) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < parts.length; i++) {
            sb.append(i == 0 ? StringTools.toLowerCaseFirstOne(parts[i]) : StringTools.toUpperCaseFirstOne(parts[i]));
        }
        return sb.toString();
    }

    /**
     * 将原始的名称经过解析后转化为首字母小写驼峰模式
     * <P>
     *
     * @param name
     * @return
     */
    public static String toFirstLowerCamelCase(String name) {
        String[] parts = autoSplit(name);
        return toFirstLowerCamelCase(parts);
    }

    /**
     * 将原始的名称经过解析后转化为下划线分割模式
     * <P>
     *
     * @param parts
     * @return
     */
    public static String toUnderLineSplitCase(String[] parts) {
        StringBuilder sb = new StringBuilder();
        for (String part : parts) {
            sb.append(StringTools.toLowerCase(part)).append(SPLIT_UNDER_LINE);
        }
        return sb.length() > 0 ? sb.substring(0, sb.length() - SPLIT_UNDER_LINE.length()) : sb.toString();
    }

    /**
     * 将原始的名称经过解析后转化为下划线分割模式
     * <P>
     *
     * @param name
     * @return
     */
    public static String toUnderLineSplitCase(String name) {
        String[] parts = autoSplit(name);
        return toUnderLineSplitCase(parts);
    }

    /**
     * 将原始的名称经过解析后转化为中线分割模式
     * <P>
     *
     * @param parts
     * @return
     */
    public static String toMiddleLineSplitCase(String[] parts) {
        StringBuilder sb = new StringBuilder();
        for (String part : parts) {
            sb.append(StringTools.toLowerCase(part)).append(SPLIT_MIDDLE_LINE);
        }
        return sb.length() > 0 ? sb.substring(0, sb.length() - SPLIT_MIDDLE_LINE.length()) : sb.toString();
    }

    /**
     * 将原始的名称经过解析后转化为中线分割模式
     * <P>
     *
     * @param name
     * @return
     */
    public static String toMiddleLineSplitCase(String name) {
        String[] parts = autoSplit(name);
        return toMiddleLineSplitCase(parts);
    }

    /**
     * 将原始的名称经过解析后转化为点分割模式
     * <P>
     *
     * @param parts
     * @return
     */
    public static String toDotSplitCase(String[] parts) {
        StringBuilder sb = new StringBuilder();
        for (String part : parts) {
            sb.append(StringTools.toLowerCase(part)).append(SPLIT_DOT);
        }
        return sb.length() > 0 ? sb.substring(0, sb.length() - SPLIT_DOT.length()) : sb.toString();
    }

    /**
     * 将原始的名称经过解析后转化为点分割模式
     * <P>
     *
     * @param name
     * @return
     */
    public static String toDotSplitCase(String name) {
        String[] parts = autoSplit(name);
        return toDotSplitCase(parts);
    }

    /**
     * 获取字符串前面的空格字符，用于格式化的相关业务中
     * <P>
     *
     * @param line
     * @return
     */
    public static String getFrontBlankStr(String line) {
        if (line == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        // 逐个处理字符
        for (char ch : line.toCharArray()) {
            if (ch <= ' ') {
                sb.append(ch);
            } else {
                break;
            }
        }
        return sb.toString();
    }

    /**
     * 判断是否是属性定义行，简单判断
     * <P>
     *
     * @param line
     * @return
     */
    public static boolean checkPropDefineLine(String line) {
        line = StringTools.subStringByIndex(line, "=");
        line = StringTools.subStringByIndex(line, ";");
        int count = 0;
        for (String part : line.trim().split(" ")) {
            String trim = part.trim();
            if (trim.equals("")) {
                continue;
            }
            if (count == 0) {
                // 如果是第一个，则判断首子是否为private
                if (!trim.equals("private")) {
                    return false;
                }
            }
            count++;
        }
        // 判断是否为3个部分
        return count == 3;
    }

}
